use std::ffi::c_void;
use crate::os::mi_os_page_size;
use crate::mimalloc::{types::*, internal::*, };
use crate::mi_assert;
pub fn mi_segment_info_size(segment: *mut MiSegment) -> usize {
    unsafe {
        (*segment).segment_info_slices * MI_SEGMENT_SLICE_SIZE
    }
}

pub fn mi_segment_page_start_from_slice(segment: *const MiSegment, slice: *const MiSlice, block_size: usize, page_size: &mut usize) -> *mut u8 {
    let idx = slice as usize - segment as usize; // 计算索引
    let psize = unsafe { (*slice).slice_count as usize * (MI_SEGMENT_SLICE_SIZE )   };
    let pstart = (segment as usize + (idx * MI_SEGMENT_SLICE_SIZE)) as *mut u8;
    
    let mut start_offset = 0;
    if block_size > 0 && block_size <= MI_MAX_ALIGN_GUARANTEE {
        let adjust = block_size - (pstart as usize % block_size);
        if adjust < block_size && psize >= (block_size + adjust)  {
            start_offset += adjust;
        }
    }
    
    if block_size >= MI_INTPTR_SIZE {
        start_offset += match block_size {
            1..=64 => 3 * block_size,
            65..=512 => block_size,
            _ => 0,
        };
    }
    
    *page_size = psize - start_offset;
    (pstart as usize + start_offset) as *mut u8
}

pub fn mi_segment_page_start(segment: *const MiSegment, page: *const MiPage, page_size: &mut usize) -> *mut u8 {
    let slice = mi_page_to_slice(page as *mut MiPage);
    let p = mi_segment_page_start_from_slice(segment, slice, mi_page_block_size(page), page_size);
    
    mi_assert!(mi_page_block_size(page) > 0 || mi_ptr_page(p as *mut c_void ) == page as *mut MiPage );
    mi_assert!(mi_ptr_segment(p as *mut c_void ) == segment as *mut MiSegment );
    
    p
}

pub fn mi_segment_calculate_slices(mut required: usize, info_slices: &mut usize) -> usize {
    let page_size = mi_os_page_size();
    let mut isize = mi_align_up(std::mem::size_of::<MiSegment>(), page_size);
    let mut guardsize = 0;

    if MI_SECURE > 0 {
        guardsize = page_size;
        if required > 0 {
            required = mi_align_up(required, MI_SEGMENT_SLICE_SIZE) + page_size;
        }
    }

    isize = mi_align_up(isize + guardsize, MI_SEGMENT_SLICE_SIZE);
    *info_slices = isize / MI_SEGMENT_SLICE_SIZE;
    
    let segment_size = if required == 0 {
        MI_SEGMENT_SIZE
    } else {
        mi_align_up(required + isize + guardsize, MI_SEGMENT_SLICE_SIZE)
    };
    
    mi_assert!(segment_size % MI_SEGMENT_SLICE_SIZE == 0);
    segment_size / MI_SEGMENT_SLICE_SIZE
}

pub fn mi_segment_page_alloc(heap: *mut MiHeap, segment: *mut MiSegment, mut block_size: usize, mut page_alignment: usize, tld: *mut MiSegmentsTld, os_tld: *mut MiOsTld) -> *mut MiPage {
    let page: *mut MiPage;
    if page_alignment > MI_BLOCK_ALIGNMENT_MAX {
        if page_alignment < MI_SEGMENT_SIZE {
            page_alignment = MI_SEGMENT_SIZE;
        }
        // TODO: Implement huge page allocation here
        // page = mi_segment_huge_page_alloc(block_size, page_alignment,unsafe {
        //        &mut (*heap).arena_id
        //} tld, os_tld)
    }
    else if block_size <= MI_SMALL_OBJ_SIZE_MAX {
        //TODO: Implement small object allocation here
        //page = mi_segments_page_alloc(heap, segment, block_size, page_alignment, tld, os_tld);
    }
    else if block_size <= MI_MEDIUM_OBJ_SIZE_MAX {
        //TODO: Implement medium object allocation here
    }
    else if block_size <= MI_LARGE_OBJ_SIZE_MAX{
        //TODO: Implement large object allocation here
    }
    else{
        //TODO: Implement huge object allocation here
    //    page = mi_segment_huge_page_alloc(block_size, page_alignment, unsafe {
     //       &mut (*heap).arena_id
      //      } tld, os_tld)
    }
    page
}

impl MiCommitMask {
    // This function corresponds to `_mi_commit_mask_committed_size`
    pub fn committed_size(&self, total: usize) -> usize {
        // Implement logic here based on the original C function
        unimplemented!()
    }

    // This function corresponds to `_mi_commit_mask_next_run`
    pub fn next_run(&self, idx: &mut usize) -> usize {
        // Implement logic here based on the original C function
        unimplemented!()
    }
}
